package com.ylr.base.common.tool;

import com.ylr.base.common.enums.ResultEnum;
import com.ylr.base.common.constant.Constant;
import com.ylr.base.common.exception.YlrException;
import com.ylr.base.common.interfaces.BaseResultEnum;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.slf4j.MDC;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wei
 * date: 2022-03-18 16:49:28
 * className: Result http请求结果类
 * version: 1.0
 * description:
 *  `@JsonInclude(JsonInclude.Include.NON_NULL)`: 序列化时不操作空属性
 */
@Getter
@Setter
@ToString
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Result<T> {

    /**
     * 状态码
     */
    protected Integer code;

    /**
     * 回复消息
     */
    protected String msg;

    /**
     * 请求结果
     */
    private T data;

    /**
     * 请求主键
     */
    private String requestId;

    private Result() {
    }

    /**
     * 判断是否请求成功
     * @return true-成功 false-失败
     */
    public boolean isSuccess() {
        return ResultEnum.SUCCESS.getCode().equals(code);
    }

    /**
     * 判断是否请求失败
     * @return true-失败 false-成功
     */
    @JsonIgnore
    public boolean isFail() {
        return !isSuccess();
    }

    /**
     * 重构结果对象
     * 以适应泛型检查
     * @return 新结果对象
     */
    @JsonIgnore
    public Result<T> rebuild() {
        return getResult(this);
    }

    public static <T> Result<T> success(T data) {
        Result<T> result = success();
        result.data = data;
        return result;
    }

    public static <T> Result<T> success() {
        return getResult(ResultEnum.SUCCESS);
    }

    public static <T> Result<T> fail() {
        return getResult(ResultEnum.SERVICE_FAIL);
    }

    public static <T> Result<T> fail(Integer code) {
        return getResult(code, ResultEnum.SERVICE_FAIL.getMsg());
    }

    public static <T> Result<T> fail(String message) {
        return getResult(ResultEnum.SERVICE_FAIL.getCode(), message);
    }

    /**
     * 封装接口请求参数错误反馈信息
     * @return 结果对象
     */
    public static <T> Result<T> paramFail() {
        return getResult(ResultEnum.PARAM_FAIL);
    }

    /**
     * 批量处理数量超过设定阈值，返回错误数据
     * @return 结果对象
     */
    public static <T> Result<T> batchFail() {
        return getResult(ResultEnum.BATCH_FAIL);
    }

    /**
     * 客户端请求失败，返回错误数据
     * @return 结果对象
     */
    public static <T> Result<T> requestFail() {
        return getResult(ResultEnum.REQUEST_FAIL);
    }

    /**
     * 有客户端请求数据导致操作失败，返回错误数据
     * @param message 提示消息
     * @return 结果对象
     */
    public static <T> Result<T> requestFail(String message) {
        return getResult(ResultEnum.REQUEST_FAIL.getCode(), message);
    }


    public static <T> Result<T> getResult(Integer code, String message) {
        Result<T> result = new Result<>();
        result.code = code;
        result.msg = message;
        result.requestId = MDC.get(Constant.TRACE_ID);
        return result;
    }

    public static <T> Result<T> getResult(BaseResultEnum resultEnum) {
        Result<T> result = new Result<>();
        result.code = resultEnum.getCode();
        result.msg = resultEnum.getMsg();
        result.requestId = MDC.get(Constant.TRACE_ID);
        return result;
    }

    public static <T> Result<T> getResult(BaseResultEnum resultEnum, T data) {
        Result<T> result = new Result<>();
        result.code = resultEnum.getCode();
        result.msg = resultEnum.getMsg();
        result.data = data;
        result.requestId = MDC.get(Constant.TRACE_ID);
        return result;
    }

    public static <T> Result<T> getResult(Integer code, String message, T data) {
        Result<T> result = new Result<>();
        result.code = code;
        result.msg = message;
        result.data = data;
        result.requestId = MDC.get(Constant.TRACE_ID);
        return result;
    }

    public static <T> Result<T> getResult(YlrException ylrException) {
        Result<T> result = new Result<>();
        result.code = ylrException.getCode();
        result.msg = ylrException.getMessage();
        result.requestId = MDC.get(Constant.TRACE_ID);
        return result;
    }

    /**
     * 重新组装结果对象
     * @param res 旧结果对象
     * @return 新结果对象
     * @param <T> 泛型类型
     * @param <U> 泛型类型
     */
    public static <T, U> Result<T> getResult(Result<U> res) {
        Result<T> result = new Result<>();
        result.code = res.code;
        result.msg = res.msg;
        result.requestId = res.requestId;
        return result;
    }

}